package com.dashu.core.service;

import com.dashu.base.enums.ReplRyCode;
import com.dashu.core.dto.company.CompanyDTO;
import com.dashu.core.model.CompanyCls;
import com.dashu.core.result.PageEnty;
import com.dashu.base.utils.CopyUtil;
import com.dashu.base.utils.UIDUtil;
import com.dashu.base.utils.VerificationUtil;
import com.dashu.core.dto.company.CompanyDepartmentDTO;
import com.dashu.core.handler.VerificationException;
import com.dashu.core.model.CompanyDepartment;
import com.dashu.core.model.QCompanyDepartment;
import com.dashu.core.vo.company.CompanyDepartmentVO;
import com.dashu.core.vo.UpdateEntityVO;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.persistence.FlushModeType;
import javax.transaction.Transactional;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class CompanyDepartmentService extends DataService {

    @Autowired
    private CompanyService companyService;
    @Autowired
    private CompanyClsService companyClsService;

    @Transactional
    public CompanyDepartmentDTO add(CompanyDepartmentVO companyDepartmentVO) {
        CompanyDepartment companyDepartment = CopyUtil.copyEnty(companyDepartmentVO, CompanyDepartment.class);
        try {
            long userId = Long.parseLong(VerificationUtil.getUserId());
            companyDepartment.setId(UIDUtil.nextId());
            companyDepartment.setCreateUser(userId);
            companyDepartment.setCreateTime(System.currentTimeMillis());
            entityManager.persist(companyDepartment);
//            entityManager.flush();
            entityManager.setFlushMode(FlushModeType.AUTO);
        } catch (Exception e) {
            e.printStackTrace();
            throw new VerificationException(ReplRyCode.DATA_NOT_INVALID, ReplRyCode.DATA_NOT_INVALID.getMessage());
        }
        CompanyDepartmentDTO companyDepartmentDTO = CopyUtil.copyEnty(companyDepartment, CompanyDepartmentDTO.class);
        return companyDepartmentDTO;

    }

    @Transactional
    public boolean deleteByCompanyDepartmentId(long companyDepartmentId) {
        QCompanyDepartment qCompanyDepartment = QCompanyDepartment.companyDepartment;
        List<CompanyCls> companyCls = companyClsService.findByDepartmentId(companyDepartmentId);
        if (companyCls.size() > 0)
            throw new VerificationException(ReplRyCode.EXIST_GL_CLS, ReplRyCode.EXIST_GL_CLS.getMessage());
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompanyDepartment.id.eq(companyDepartmentId));
        CompanyDepartment companyDepartment;
        queryFactory.select();
        companyDepartment = queryFactory
                .select(qCompanyDepartment)
                .from(qCompanyDepartment)
                .where(booleanBuilder.getValue()).fetchOne();
        if (companyDepartment == null)
            throw new VerificationException(ReplRyCode.COMPANY_NOT_DATA, ReplRyCode.COMPANY_NOT_DATA.getMessage());
        entityManager.remove(companyDepartment);
//            entityManager.flush();
        entityManager.setFlushMode(FlushModeType.AUTO);
        return true;
    }

    @Transactional
    public CompanyDepartmentDTO updataByCompanyDepartmentId(UpdateEntityVO<CompanyDepartmentVO> updateCompanyDepartmentVO) throws Exception {
        QCompanyDepartment qCompanyDepartment = QCompanyDepartment.companyDepartment;
        long userId = Long.parseLong(VerificationUtil.getUserId());
        CompanyDepartmentVO companyDepartmentVO = updateCompanyDepartmentVO.getEntityVO();
        CompanyDepartmentDTO companyDepartmentDTO = existByCompanyDepartmentName(companyDepartmentVO.getGradeName(),companyDepartmentVO.getCompanyId());
        if (companyDepartmentDTO != null) {
            throw new VerificationException(ReplRyCode.EXIST_COMPANY_DEPARTMENT, ReplRyCode.EXIST_COMPANY_DEPARTMENT.getMessage());
        }
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompanyDepartment.id.eq(updateCompanyDepartmentVO.getId()));
        CompanyDepartment companyDepartment;
        try {
            companyDepartment = queryFactory
                    .select(qCompanyDepartment)
                    .from(qCompanyDepartment)
                    .where(booleanBuilder.getValue()).fetchOne();
            if (companyDepartment == null)
                throw new VerificationException(ReplRyCode.COMPANY_NOT_DATA, ReplRyCode.COMPANY_NOT_DATA.getMessage());
            companyDepartment.setUpdateUser(userId);
            companyDepartment.setUpdateTime(new Date().getTime());
            if (companyDepartmentVO.getGradeName() != null)
                companyDepartment.setGradeName(companyDepartmentVO.getGradeName());
            if (companyDepartmentVO.getCompanyId() != 0)
                companyDepartment.setCompanyId(companyDepartmentVO.getCompanyId());
            companyDepartment = entityManager.merge(companyDepartment);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
//        entityManager.flush();
        entityManager.setFlushMode(FlushModeType.AUTO);
        CompanyDepartmentDTO CompanyDepartmentDTO = CopyUtil.copyEnty(companyDepartment, CompanyDepartmentDTO.class);
        return CompanyDepartmentDTO;

    }

    public List<CompanyDepartmentDTO> findByCreteUser(PageEnty<Long> baseVo) {
        QCompanyDepartment qCompanyDepartment = QCompanyDepartment.companyDepartment;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompanyDepartment.createUser.eq(baseVo.getBaseId()));
        List<CompanyDepartment> companyDepartments = queryFactory
                .select(qCompanyDepartment)
                .from(qCompanyDepartment)
                .where(booleanBuilder.getValue())
                .fetch();
        List<CompanyDepartmentDTO> recycleDTOS = CopyUtil.copyList(companyDepartments, CompanyDepartmentDTO.class);
        return recycleDTOS;

    }

    public CompanyDepartmentDTO findByCompanyDepartmentId(long companyDepartmentId) {
        QCompanyDepartment qCompanyDepartment = QCompanyDepartment.companyDepartment;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompanyDepartment.id.eq(companyDepartmentId));
        CompanyDepartment companyDepartment = queryFactory
                .select(qCompanyDepartment)
                .from(qCompanyDepartment)
                .where(booleanBuilder.getValue()).fetchOne();
        CompanyDepartmentDTO CompanyDepartmentDTO = CopyUtil.copyEnty(companyDepartment, CompanyDepartmentDTO.class);
        return CompanyDepartmentDTO;

    }

    public CompanyDepartmentDTO existByCompanyDepartmentName(String companyDepartmentName, long companyDepartmentId) {
        QCompanyDepartment qCompanyDepartment = QCompanyDepartment.companyDepartment;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompanyDepartment.gradeName.eq(companyDepartmentName));
        booleanBuilder.and(qCompanyDepartment.companyId.eq(companyDepartmentId));
        CompanyDepartment companyDepartment = queryFactory
                .select(qCompanyDepartment)
                .from(qCompanyDepartment)
                .where(booleanBuilder.getValue()).fetchOne();
        CompanyDepartmentDTO CompanyDepartmentDTO = CopyUtil.copyEnty(companyDepartment, CompanyDepartmentDTO.class);
        return CompanyDepartmentDTO;

    }


    public long departmentCount(PageEnty<CompanyDepartmentVO> departmentListPageEntyVO) throws Exception {
        QCompanyDepartment qCompanyDepartment = QCompanyDepartment.companyDepartment;
        long userId = Long.parseLong(VerificationUtil.getUserId());
        if (departmentListPageEntyVO.getVo() == null)
            throw new VerificationException(ReplRyCode.DATA_ERROR, ReplRyCode.DATA_ERROR.getMessage());
        CompanyDepartmentVO companyDepartmentVO = departmentListPageEntyVO.getVo();
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        long baseId = departmentListPageEntyVO.getBaseId() == 0 ? userId : departmentListPageEntyVO.getBaseId();
//        booleanBuilder.and(qCompany.baseId.eq(userId));
        if (companyDepartmentVO.getCompanyId() != 0) {
            booleanBuilder.and(qCompanyDepartment.companyId.eq(companyDepartmentVO.getCompanyId()));
        } else if (!StringUtils.isEmpty(companyDepartmentVO.getGradeName())) {
            booleanBuilder.and(qCompanyDepartment.gradeName.eq(companyDepartmentVO.getGradeName()));
        } else {
            List<Long> companys = Lists.newArrayList();
            companyService.findByBaseId(baseId).stream().forEach(cd -> {
                companys.add(cd.getId());
            });
            booleanBuilder.and(qCompanyDepartment.companyId.in(companys));
        }
        long count = queryFactory
                .select(qCompanyDepartment.count())
                .from(qCompanyDepartment)
                .where(booleanBuilder.getValue())
                .fetchCount();
        return count;
    }

    public List<CompanyDepartmentDTO> pageDepartmentList(PageEnty<CompanyDepartmentVO> departmentListPageEntyVO) throws Exception {
        QCompanyDepartment qCompanyDepartment = QCompanyDepartment.companyDepartment;
        long userId = Long.parseLong(VerificationUtil.getUserId());
        List<CompanyDepartmentDTO> companyDepartmentDTOS = Lists.newArrayList();
        if (departmentListPageEntyVO.getVo() == null)
            throw new VerificationException(ReplRyCode.DATA_ERROR, ReplRyCode.DATA_ERROR.getMessage());
        CompanyDepartmentVO companyDepartmentVO = departmentListPageEntyVO.getVo();
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        long baseId = departmentListPageEntyVO.getBaseId() == 0 ? userId : departmentListPageEntyVO.getBaseId();
//        booleanBuilder.and(qCompany.baseId.eq(userId));
        if (companyDepartmentVO.getCompanyId() != 0) {
            booleanBuilder.and(qCompanyDepartment.companyId.eq(companyDepartmentVO.getCompanyId()));
        } else if (!StringUtils.isEmpty(companyDepartmentVO.getGradeName())) {
            booleanBuilder.and(qCompanyDepartment.gradeName.like("%"+companyDepartmentVO.getGradeName()+"%"));
        } else {
            List<Long> companys = Lists.newArrayList();
            companyService.findByBaseId(baseId).stream().forEach(cd -> {
                companys.add(cd.getId());
            });
            booleanBuilder.and(qCompanyDepartment.companyId.in(companys));
        }
        List<CompanyDepartment> companyDepartments = queryFactory
                .select(qCompanyDepartment)
                .from(qCompanyDepartment)
                .where(booleanBuilder.getValue())
                .offset((departmentListPageEntyVO.getPage() - 1) * departmentListPageEntyVO.getNum())
                .limit(departmentListPageEntyVO.getNum())
                .orderBy(qCompanyDepartment.createTime.desc())
                .fetch();
        companyDepartments.stream().forEach(cd -> {
            CompanyDepartmentDTO companyDepartmentDTO = new CompanyDepartmentDTO();
            companyDepartmentDTO.setId(cd.getId());
            companyDepartmentDTO.setCreateTime(cd.getCreateTime());
            companyDepartmentDTO.setGradeName(cd.getGradeName());
            CompanyDTO companyDTO = companyService.findByCompanyId(cd.getCompanyId());
            companyDepartmentDTO.setCompanyName(companyDTO.getCompanyName());
            companyDepartmentDTOS.add(companyDepartmentDTO);
        });
        return companyDepartmentDTOS;

    }

    public List<CompanyDepartment> findByCompanyId(long companyId) {
        QCompanyDepartment qCompanyDepartment = QCompanyDepartment.companyDepartment;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qCompanyDepartment.companyId.eq(companyId));
        List<CompanyDepartment> companyDepartments = queryFactory
                .select(qCompanyDepartment)
                .from(qCompanyDepartment)
                .where(booleanBuilder.getValue())
                .fetch();
        return companyDepartments;

    }

}
